package com.xdxc.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

@MappedTypes({List.class, Map.class})
@MappedJdbcTypes(org.apache.ibatis.type.JdbcType.VARCHAR)
public class JsonTypeHandler<T> extends BaseTypeHandler<T> {

    private static final ObjectMapper mapper = new ObjectMapper();
    private final Class<T> type;

    public JsonTypeHandler(Class<T> type) {
        if (type == null) {
            throw new IllegalArgumentException("Type argument cannot be null");
        }
        this.type = type;
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, toJson(parameter));
    }

    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String json = rs.getString(columnName);
        return json != null ? parseJson(json) : null;
    }

    @Override
    public T getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
        String json = resultSet.getString(columnIndex);
        return json != null ? parseJson(json) : null;
    }

    @Override
    public T getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        String json = callableStatement.getString(columnIndex);
        return json != null ? parseJson(json) : null;
    }

    private String toJson(T obj) {
        try {
            return mapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON转换失败", e);
        }
    }

    @SuppressWarnings("unchecked")
    private T parseJson(String json) {
        try {
            if (type.equals(List.class)) {
                // 假设 List 中的元素是 String 类型
                return (T) mapper.readValue(json, new TypeReference<List<String>>() {});
            } else if (type.equals(Map.class)) {
                // 假设 Map 的键值对是 <String, Object>
                return (T) mapper.readValue(json, new TypeReference<Map<String, Object>>() {});
            } else {
                // 其他类型直接反序列化
                return mapper.readValue(json, type);
            }
        } catch (IOException e) {
            throw new RuntimeException("JSON解析失败", e);
        }
    }
}